package Shop01;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.*;
import java.util.Properties;

/**
 * 商品服务类，负责商品相关的业务逻辑
 * 目前使用内存Map模拟数据库
 */
public class ProductService {

    // 使用Map存储商品数据，key是商品ID，value是商品对象
    // 优点：通过ID查找商品时，时间复杂度是O(1)，非常高效
    private Map<String, Product> productData = new HashMap<>();
    private String dataFilePath = "products.dat"; // 默认数据文件路径

    /**
     * 构造函数，初始化商品数据
     * 优先从文件加载数据，如果加载失败则使用默认数据
     */
    public ProductService() {
        // 加载配置文件
        loadConfig();

        // 最先调用loadData()尝试从文件加载数据
        boolean loadSuccess = loadData();

        // 如果加载失败，则使用默认数据
        if (!loadSuccess) {
            System.out.println("使用默认商品数据初始化...");
            initializeDefaultData();
        }
    }

    /**
     * 加载配置文件
     */
    private void loadConfig() {
        Properties props = new Properties();
        File configFile = new File("config.properties");

        if (!configFile.exists()) {
            System.out.println("配置文件 config.properties 不存在，使用默认数据文件路径: " + dataFilePath);
            return;
        }

        try (InputStreamReader reader = new InputStreamReader(
                new FileInputStream("config.properties"), "UTF-8")) {

            props.load(reader);
            String filePath = props.getProperty("data.file.path");

            if (filePath != null && !filePath.trim().isEmpty()) {
                dataFilePath = filePath.trim();
                System.out.println("从配置文件读取数据文件路径: " + dataFilePath);
            } else {
                System.out.println("配置文件中未找到 data.file.path 属性或属性值为空，使用默认路径: " + dataFilePath);
            }

        } catch (IOException e) {
            System.err.println("读取配置文件失败: " + e.getMessage());
            System.out.println("使用默认数据文件路径: " + dataFilePath);
        }
    }

    /**
     * 初始化默认数据
     */
    private void initializeDefaultData() {
        productData.put("p001", new Product("p001", "Java从入门到精通", 99.0, 100));
        productData.put("p002", new Product("p002", "高性能MySQL", 128.5, 50));
        productData.put("p003", new Product("p003", "颈椎康复指南", 45.0, 200));
        productData.put("p004", new Product("p004", "生发秘籍", 88.0, 0)); // 库存为0的商品
        productData.put("p005", new Product("p005", "2025新款女装", 109.0, 20));
        productData.put("p006", new Product("p006", "铠侠sd10固态硬盘", 519.0, 100));
    }

    /**
     * 获取所有商品列表
     * @return 商品列表
     */
    public List<Product> getAllProducts() {
        // 从Map的值集合创建一个新的ArrayList并返回
        return new ArrayList<>(productData.values());
    }

    /**
     * 根据ID查找商品
     * @param id 商品ID
     * @return 找到的商品对象，如果不存在则返回null
     */
    public Product findProductById(String id) {
        return productData.get(id);
    }

    /**
     * 保存商品数据到文件
     * @return 保存成功返回true，失败返回false
     */
    public boolean saveData() {
        try {
            // 确保目录存在
            File file = new File(dataFilePath);
            File parentDir = file.getParentFile();
            if (parentDir != null && !parentDir.exists()) {
                boolean dirsCreated = parentDir.mkdirs();
                if (!dirsCreated) {
                    System.err.println("创建目录失败: " + parentDir.getAbsolutePath());
                    return false;
                }
            }

            try (ObjectOutputStream oos = new ObjectOutputStream(
                    new FileOutputStream(dataFilePath))) {
                oos.writeObject(productData);
                System.out.println("商品数据已成功保存到文件: " + dataFilePath);
                return true;
            }
        } catch (IOException e) {
            System.err.println("保存商品数据失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 从文件加载商品数据
     * @return 加载成功返回true，失败返回false
     */
    @SuppressWarnings("unchecked")
    public boolean loadData() {
        File file = new File(dataFilePath);
        if (!file.exists()) {
            System.out.println("数据文件不存在: " + dataFilePath);
            return false;
        }

        if (!file.canRead()) {
            System.err.println("无法读取数据文件: " + dataFilePath);
            return false;
        }

        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(dataFilePath))) {
            Object obj = ois.readObject();
            if (obj instanceof Map) {
                productData = (Map<String, Product>) obj;
                System.out.println("商品数据已从文件加载: " + dataFilePath);
                System.out.println("加载了 " + productData.size() + " 个商品");
                return true;
            } else {
                System.err.println("文件格式不正确");
                return false;
            }
        } catch (IOException | ClassNotFoundException e) {
            System.err.println("加载商品数据失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 备份数据文件
     * @return 备份成功返回true，失败返回false
     */
    public boolean backupData() {
        File sourceFile = new File(dataFilePath);
        String backupFilePath = dataFilePath + ".bak";
        File backupFile = new File(backupFilePath);

        // 检查源文件是否存在
        if (!sourceFile.exists()) {
            System.err.println("源文件不存在，无法备份: " + dataFilePath);
            return false;
        }

        // 使用FileInputStream和FileOutputStream进行文件复制
        try (FileInputStream fis = new FileInputStream(sourceFile);
             FileOutputStream fos = new FileOutputStream(backupFile)) {

            // 创建缓冲区
            byte[] buffer = new byte[1024];
            int bytesRead;

            // 循环读取和写入数据
            while ((bytesRead = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }

            System.out.println("数据备份成功: " + backupFilePath);
            return true;

        } catch (IOException e) {
            System.err.println("备份数据失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 添加新商品
     * @param product 要添加的商品
     */
    public void addProduct(Product product) {
        productData.put(product.getId(), product);
    }

    /**
     * 删除商品
     * @param id 要删除的商品ID
     */
    public void removeProduct(String id) {
        productData.remove(id);
    }

    /**
     * 获取商品数量
     * @return 商品总数
     */
    public int getProductCount() {
        return productData.size();
    }

    /**
     * 获取当前数据文件路径
     * @return 数据文件路径
     */
    public String getDataFilePath() {
        return dataFilePath;
    }

    /**
     * 测试类 - 作为静态内部类实现
     */
    public static class TestProductService {
        public static void main(String[] args) {
            System.out.println("=== 测试商品服务 ===");

            // 创建服务实例，会自动尝试加载数据
            ProductService service = new ProductService();
            System.out.println("当前数据文件路径: " + service.getDataFilePath());

            System.out.println("当前商品数量: " + service.getProductCount());

            // 显示所有商品
            System.out.println("\n=== 所有商品 ===");
            List<Product> products = service.getAllProducts();
            for (Product p : products) {
                System.out.println(p);
            }

            // 添加新商品
            System.out.println("\n=== 添加新商品 ===");
            service.addProduct(new Product("p007", "测试商品", 29.9, 50));
            System.out.println("添加后商品数量: " + service.getProductCount());

            // 保存数据
            System.out.println("\n=== 保存数据 ===");
            boolean saveSuccess = service.saveData();
            System.out.println("保存结果: " + (saveSuccess ? "成功" : "失败"));

            // 备份数据
            System.out.println("\n=== 备份数据 ===");
            boolean backupSuccess = service.backupData();
            System.out.println("备份结果: " + (backupSuccess ? "成功" : "失败"));

            // 创建新的服务实例验证数据是否持久化
            System.out.println("\n=== 重新加载数据 ===");
            ProductService service2 = new ProductService();
            System.out.println("重新加载后商品数量: " + service2.getProductCount());

            // 显示重新加载后的所有商品
            System.out.println("\n=== 重新加载后的所有商品 ===");
            List<Product> reloadedProducts = service2.getAllProducts();
            for (Product p : reloadedProducts) {
                System.out.println(p);
            }

            System.out.println("\n=== 测试完成 ===");
        }
    }
}